/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jama.carouselview.views;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Component.DraggedListener;
import ohos.agp.components.DragInfo;
import ohos.agp.components.ListContainer;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

/**
 * 自定义ListContainer，应当作为嵌套ListContainer的外层ListContainer，已解决滑动冲突（不同方向）
 *
 * @since 2021-04-19
 */
public class BaseCarouselView extends ListContainer implements DraggedListener, ListContainer.ItemLongClickedListener {
    private static final String TAG = BaseCarouselView.class.getSimpleName();
    private static final HiLogLabel LOG_LABEL = new HiLogLabel(0, 0, "BaseCarouselView");
    private static final int NUM_80 = 80;
    private static final int NUM_3 = 3;
    private static final int NUM_4 = 4;
    private float startX;
    private Display display;
    private boolean isFlag = true;
    private int lastViewPos = -1;

    /**
     * BaseDependentLayout的构造方法，在Java类中new时调用
     *
     * @param context
     */
    public BaseCarouselView(Context context) {
        super(context);
        init(context);
    }

    /**
     * BaseDependentLayout的构造方法，在xml布局中
     *
     * @param context
     * @param attrSet
     */
    public BaseCarouselView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(context);
    }

    /**
     * BaseDependentLayout的构造方法，在xml布局且加Style时调用
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public BaseCarouselView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context);
    }

    private void init(Context context) {
        setDraggedListener(DRAG_HORIZONTAL, this);
        display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        invalidate();
        setItemLongClickedListener(this);
        setLongClickable(false);
        setReboundEffect(true);
    }

    /**
     * onDragDown
     *
     * @param component component
     * @param dragInfo  dragInfo
     */
    @Override
    public void onDragDown(Component component, DragInfo dragInfo) {
    }

    /**
     * onDragStart
     *
     * @param component component
     * @param dragInfo  dragInfo
     */
    @Override
    public void onDragStart(Component component, DragInfo dragInfo) {
        Point downPoint = dragInfo.startPoint;
        startX = downPoint.getPointX();
    }

    /**
     * onDragUpdate
     *
     * @param component component
     * @param dragInfo  dragInfo
     */
    @Override
    public void onDragUpdate(Component component, DragInfo dragInfo) {
        scrollBy((int) -dragInfo.xOffset, 0);
    }

    /**
     * onDragEnd
     *
     * @param component component
     * @param dragInfo  dragInfo
     */
    @Override
    public void onDragEnd(Component component, DragInfo dragInfo) {

        Point downPoint = dragInfo.updatePoint;
        float mDownX = downPoint.getPointX();
        float gap = startX - mDownX;
        if (gap < 0) {
            changeFirst(gap);
        } else if (gap > 0) {
            int index = getFirstVisibleItemPosition();

            if (gap > NUM_80) {
                index++;
            }
            if (getLastVisibleItemPosition() == getItemProvider().getCount() - 1 && getFirstVisibleItemPosition() != NUM_3) {
                return;
            }
            scrollTo(index);
            invalidate();
        }
    }

    private void changeFirst(float gap) {
        int firstVisibleItemPosition1 = getFirstVisibleItemPosition();
        if (firstVisibleItemPosition1 == 0) {
            debug("firstVisibleItemPosition1 == 0");
            return;
        }
        if (gap < -NUM_80) {
            if (firstVisibleItemPosition1 - 1 != 0 || firstVisibleItemPosition1 - 1 != 1) {
                scrollTo(--firstVisibleItemPosition1);
                invalidate();
            }
            return;
        }
        if (firstVisibleItemPosition1 == 1) {
            scrollTo(firstVisibleItemPosition1 + 2);
            invalidate();
            return;
        }
        checkFirstVisible(firstVisibleItemPosition1);

        invalidate();
    }

    private void checkFirstVisible(int firstVisibleItemPosition1) {
        if (firstVisibleItemPosition1 == NUM_3) {
            if (firstVisibleItemPosition1 - 1 != 0) {
                scrollTo(getFirstVisibleItemPosition() - 1);
                invalidate();
            }
            return;
        }
        if (getLastVisibleItemPosition() == getItemProvider().getCount() - 1) {
            return;
        }
        if (firstVisibleItemPosition1 == NUM_3 || firstVisibleItemPosition1 == NUM_4) {

            scrollTo(NUM_3);
            invalidate();
            return;
        }
        if (firstVisibleItemPosition1 == 0 || firstVisibleItemPosition1 == 1 || firstVisibleItemPosition1 == 2) {
            scrollTo(firstVisibleItemPosition1);
            invalidate();
            return;
        }

    }

    /**
     * setLongClickable
     *
     * @param longClickable longClickable
     */
    @Override
    public void setLongClickable(boolean longClickable) {
        super.setLongClickable(false);
    }

    /**
     * executeLongClick
     *
     * @return executeLongClick
     */
    @Override
    public boolean executeLongClick() {
        return false;
    }

    /**
     * onDragCancel
     *
     * @param component Component
     * @param dragInfo  dragInfo
     */
    @Override
    public void onDragCancel(Component component, DragInfo dragInfo) {
    }

    /**
     * onItemLongClicked
     *
     * @param parent    parent
     * @param component component
     * @param position  position
     * @param id        id
     * @return boolean
     */
    @Override
    public boolean onItemLongClicked(ListContainer parent, Component component, int position, long id) {
        return true;
    }

    private void debug(String msg) {
        HiLog.error(LOG_LABEL, msg);
    }
}